package com.wanlian.dao.impl;

import com.wanlian.common.PageCondition;
import com.wanlian.dao.DeviceDataDao;
import com.wanlian.entity.Device;
import com.wanlian.entity.DeviceData;
import com.wanlian.model.ResultModel;
import com.wanlian.util.DateUtil;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;


@Component
public class DeviceDataDaoImpl extends GenericDaoImpl<DeviceData> implements DeviceDataDao {

    public DeviceDataDaoImpl() {
        super(DeviceData.class);
    }

    @Override
    public ResultModel queryDeviceDataByParams(PageCondition pageCondition) {
        String[] column = {"username", "phone", "devicename", "macaddress", "deviceid", "modifytime", "devicekey", "onlineLv", "onlinetime"};
        String sql = " select u.username,u.phone,d.devicename,d.macaddress,d.deviceid,dd.modifytime,d.devicekey,dd.onlineLv,dd.onlinetime from " +
                " tb_user u,tb_device d,tb_devicedata dd where d.userid=u.id and dd.devicekey=d.devicekey and u.isenable=true ";

        StringBuilder sqlWhere = new StringBuilder();
        ArrayList<Object> param = new ArrayList<Object>();

        if (pageCondition.isEmpty("phone")) {
            String phone = (String) pageCondition.getByKey("phone");
            sqlWhere.append(" and u.phone=?");
            param.add(phone);
        }

        if (pageCondition.isEmpty("macAddress")) {
            String macAddress = (String) pageCondition.getByKey("macAddress");
            sqlWhere.append(" and d.macAddress like ? ");
            param.add("%" + macAddress + "%");
        }

        if (pageCondition.isEmpty("deviceId")) {
            String deviceId = (String) pageCondition.getByKey("deviceId");
            sqlWhere.append(" and d.deviceid like ? ");
            param.add("%" + deviceId + "%");
        }

        if (pageCondition.isEmpty("devicekey")) {
            String devicekey = (String) pageCondition.getByKey("devicekey");
            sqlWhere.append(" and d.devicekey like ? ");
            param.add("%" + devicekey + "%");
        }
        sqlWhere.append(" order by dd.modifytime desc, onlinetime desc ");
        List<Map<String, Object>> lists = this.queryForListObjectByPage(sql + sqlWhere + "", param.toArray(), pageCondition.getPage(), column);
        int count = this.queryCountByParam("select count(1) from tb_user u,tb_device d,tb_devicedata dd where d.userid=u.id and dd.devicekey=d.devicekey and u.isenable=true  " + sqlWhere, param.toArray());
        ResultModel resultModel = new ResultModel(true, lists, count);
        return resultModel;
    }


    @Override
    public DeviceData queryByDate(String key, Timestamp timestamp) {
        String hql = String.format("from %s where modifytime=? and devicekey=?", entityClassName());
        DeviceData deviceData = this.queryForObject(hql, new Object[]{timestamp, key});
        return deviceData;
    }

    @Override
    public DeviceData queryByKey(String deviceKey) {
        Date dateEnd = DateUtil.addDay(DateUtil.currentDate(), -1);
        String endDate = "";
        try {
            endDate = DateUtil.formatDateNoHour(dateEnd);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        String hql = String.format("from %s where devicekey=? and modifytime=? ", entityClassName());
        DeviceData deviceData = this.queryForObject(hql, new Object[]{deviceKey, endDate});
        return deviceData;
    }

    @Override
    public List<DeviceData> queryAllData(String date) {
        Timestamp timestamp = Timestamp.valueOf(date + " 00:00:00.00");
        String hql = String.format("from %s where modifytime=? ", entityClassName());
        List<DeviceData> deviceDatas = this.queryForList(hql, new Object[]{timestamp});
        return deviceDatas;
    }

    @Override
    public Map<String, DeviceData> queryAllData(Timestamp timestamp) {
        String hql = String.format("from %s where modifytime=? ", entityClassName());
        List<DeviceData> deviceDatas = this.queryForList(hql, new Object[]{timestamp});
        Map<String, DeviceData> deviceDataMap = new HashMap<>();
        for (DeviceData item : deviceDatas) {
            if (!deviceDataMap.containsKey(item.getDeviceKey())) {
                deviceDataMap.put(item.getDeviceKey(), item);
            }
        }
        return deviceDataMap;
    }

    @Override
    public void editBatch(List<DeviceData> deviceData) {
        StringBuilder sql = new StringBuilder();
        String param="";
        sql.append("update tb_devicedata  set  onlinetime = case devicekey ");
        for (DeviceData dData : deviceData) {
            param = param +"'"+ dData.getDeviceKey() + "',";
            sql.append(" when '" + dData.getDeviceKey() + "' then " + dData.getOnlineTime());
        }
        sql.append(" end ,");
        sql.append(" onlinelv= case devicekey ");
        for (DeviceData deviceData1 : deviceData) {
            sql.append(" when '" + deviceData1.getDeviceKey() + "' then " + deviceData1.getOnlineLv());
        }
        sql.append(" end ");
        param = param.substring(0, param.length() - 1);
        sql.append(" where devicekey in (" + param + ") and modifytime='"+DateUtil.currentDateTimestamp() +"'");
        this.updateByJdbc(sql.toString(),null);
    }

    @Override
    public void doInsertBatch(List<DeviceData> deviceData) {
        Session session = this.currentSession();
        Work work = new Work() {
            @Override
            public void execute(Connection connection) throws SQLException {
                PreparedStatement stmt = connection.prepareStatement(
                        "INSERT INTO tb_devicedata( modifytime,devicekey,onlinelv,onlinetime)" +
                                " VALUES(?,?,?,?)");
                for (DeviceData deviceData1 : deviceData) {
                    stmt.setTimestamp(1, deviceData1.getModifyTime());
                    stmt.setString(2, deviceData1.getDeviceKey());
                    stmt.setFloat(3, deviceData1.getOnlineLv());
                    stmt.setInt(4, deviceData1.getOnlineTime());
                    stmt.addBatch();
                }
                stmt.executeBatch();
            }
        };
        session.doWork(work);
    }
}
